class Person:
    def __init__(self,name):
        self._age = 0
        self.name = name
    @property
    def age(self):
        return self._age
    @age.setter
    def age(self,value):
        self._age = value


class Student(Person):
    def __init__(self,name,school):
        super(Student, self).__init__(name)
        self.school = school

    def __getattr__(self, item):
        print(f"{item} 找不到，继续被访问")
        return None
    def __getattribute__(self, item):
        print(f"{item} 被访问")
        super(Student, self).__getattribute__(item)

s = Student("jack","清华大学")

s.address  # 如果不实现 __getattr__就会抛异常


import numbers
# 属性描述符
class IntField:
    def __get__(self, instance, owner):
        return self.value
    def __set__(self, instance, value):
        if isinstance(value,numbers.Integral):
            #注意不要 instance.age = value 这样会导致递归调用死循环
            self.value = value
        else:
            raise ValueError("int value need")
    def __delete__(self, instance):
        pass

class NoDataField:
    #仅实现 __get__
    def __get__(self, instance, owner):
        pass

class Dog:
    age = IntField()
    def __init__(self,nickname):
        self.nick_name = nickname
d = Dog("maomao")
d.age = 3
print(d.age)

print(Dog.__dict__)   # 1、类的__dict__中查找且是属性描述符,则调用 属性描述符的 __get__
print(d.__dict__)     # 2、如果对象的__dict__中存在，则返回 instance.__dict__["age"] 否则
                      # 3、如果在类的__dict__中查找，如果存在 且属于 nodata 属性描述符,则返回属性描述符的__get__
                     #     否则返回 Class.__dict__["age"]


